package com.cloud.mall.conf.gateway;

import cn.hutool.json.JSONUtil;
import com.cloud.mall.enums.ExcEnum;
import com.cloud.mall.enums.HeaderEnum;
import com.cloud.mall.exp.CustomException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

/**
 * @Author: 梁二东
 * @Date: 2024/12/8 10:06
 * @Description: gateway header参数全局过滤
 **/
@Component
@Slf4j
public class HeaderGlobalFilter implements GlobalFilter, Ordered {

    @Value("${cloud-mall.sign.validTimestamp}")
    private Boolean validTimestamp;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        HttpHeaders headers = request.getHeaders();
        Map<String, String> headerMap = new HashMap<>();
        for (HeaderEnum header : HeaderEnum.values()) {
            headerMap.put(header.getHeaderName(), headers.getFirst(header.getHeaderName()));
            switch (header) {
                case timestamp:
                    validTimestamp(headers.getFirst(header.getHeaderName()));
                    break;
                case sign:
                    validSign(headers.getFirst(header.getHeaderName()));
                    break;
            }
        }
        log.info("headers参数：{}", JSONUtil.toJsonStr(headerMap));
        Consumer<HttpHeaders> httpHeadersConsumer = httpHeaderConsumer -> {
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                httpHeaderConsumer.set(entry.getKey(), entry.getValue());
            }
        };
        // 请求转发处理，添加新的请求头
        // 因为是使用的原始的请求对象添加了新的请求头，所以下游服务能获取到请求原有请求头和新添加的请求头
        ServerHttpRequest mutableReq = request.mutate()
                .header("global-header", "HeaderGlobalFilter")
                .headers(httpHeadersConsumer)
                .build();
        ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build();
        return chain.filter(mutableExchange);
    }

    @Override
    public int getOrder() {
//        return -2000;
        return HIGHEST_PRECEDENCE;
    }

    private void validTimestamp(String timestamp) {
        if (StringUtils.isBlank(timestamp)) {
            throw CustomException.fail(ExcEnum.BAD_REQUEST.getCode(), "请求头时间戳不能为空");
        }
        if (validTimestamp) {
            long interval = System.currentTimeMillis() / 1000 - Long.parseLong(timestamp);
            if (interval > 10 || interval < 0) {
                throw CustomException.fail(ExcEnum.BAD_REQUEST.getCode(), "请求头时间戳不合法");
            }
        }
    }
    private void validSign(String sign) {
        if (StringUtils.isBlank(sign)) {
            throw CustomException.fail(ExcEnum.BAD_REQUEST.getCode(), "请求头sign不能为空");
        }
    }
}
